package controller

import (
	"device-admin/internal/app/grpc/protoc/advertisingc"
	"device-admin/internal/app/web/service/advertising"
	"encoding/json"

	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/proto"
)

type ProtoJSONRenderer struct {
	MarshalOptions protojson.MarshalOptions
}

func NewProtoJSONRenderer() *ProtoJSONRenderer {
	return &ProtoJSONRenderer{
		MarshalOptions: protojson.MarshalOptions{
			EmitUnpopulated: true,
			UseProtoNames:   true,
			Indent:          "  ", // 可选：美化输出
		},
	}
}
func ProtoToJSON(msg proto.Message) ([]byte, error) {
	marshaler := protojson.MarshalOptions{
		EmitUnpopulated: true,
		UseProtoNames:   true,
	}

	jsonData, _ := marshaler.Marshal(msg)

	return jsonData, nil
}
func ProtoSliceToJSON(messages []proto.Message) ([]byte, error) {
	marshaler := protojson.MarshalOptions{
		EmitUnpopulated: true,
		UseProtoNames:   true,
	}

	// 手动构建 JSON 数组
	result := "["
	for i, msg := range messages {
		if i > 0 {
			result += ","
		}

		jsonData, err := marshaler.Marshal(msg)
		if err != nil {
			return nil, err
		}
		result += string(jsonData)
	}
	result += "]"

	return []byte(result), nil
}

type Advertising struct{}

// 素材列表
func (Advertising) MaterialList(c *gin.Context) {
	var params advertisingc.MaterialListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.Material{}.MaterialList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 待审核素材列表
func (Advertising) AuditMaterialList(c *gin.Context) {
	var params advertisingc.MaterialListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	params.Status = 1 //1 等待审核
	data, count, err := advertising.Material{}.MaterialList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 素材审核
func (Advertising) MaterialAudit(c *gin.Context) {
	var params advertisingc.MaterialAuditReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	params.MerchantId = c.GetString("merchant_id")
	params.MerchantName = c.GetString("merchant_name")
	params.CreateUser = c.GetString("user_id")
	params.CreateUsername = c.GetString("username")
	err := advertising.Material{}.MaterialAudit(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 素材禁用启用
func (Advertising) MaterialSwitch(c *gin.Context) {
	var params advertisingc.MaterialSwitchReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.Material{}.MaterialSwitch(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 素材审核记录
func (Advertising) MaterialAuditLogList(c *gin.Context) {
	var params advertisingc.MaterialAuditLogListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.Material{}.MaterialAuditLogList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 素材分组列表
func (Advertising) MaterialFolderList(c *gin.Context) {
	var params advertisingc.MaterialFolderListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.Material{}.MaterialFolderList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 投放计划终止
func (Advertising) PublishScheduleEnd(c *gin.Context) {
	var params advertisingc.PublishScheduleEndReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishSchedule{}.PublishScheduleEnd(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放计划列表
func (Advertising) PublishScheduleList(c *gin.Context) {
	var params advertisingc.PublishScheduleListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishSchedule{}.PublishScheduleList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 投放计划详情
func (Advertising) PublishScheduleDetail(c *gin.Context) {
	var params advertisingc.PublishScheduleDetailReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, err := advertising.PublishSchedule{}.PublishScheduleDetail(c.Request.Context(), &params)
	response.JSON(c, data, err)
}

// 投放计划列表
func (Advertising) PublishScheduleListOrderInfo(c *gin.Context) {
	var params advertisingc.SPublishScheduleListOrderInfoReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishSchedule{}.PublishScheduleListOrderInfo(c.Request.Context(), &params)
	protoItems := make([]proto.Message, len(data))
	for i, it := range data {
		protoItems[i] = it
	}
	jsonData, err := ProtoSliceToJSON(protoItems)

	var jsonObject []interface{}
	err = json.Unmarshal(jsonData, &jsonObject)
	response.JSON(c, gin.H{
		"count": count,
		"list":  jsonObject,
	}, err)
}

// 投放计划详情
func (Advertising) PublishScheduleDetailOrderInfo(c *gin.Context) {
	var params advertisingc.SPublishScheduleDetailOrderInfoReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, err := advertising.PublishSchedule{}.PublishScheduleDetailOrderInfo(c.Request.Context(), &params)
	if err != nil {
		response.JSON(c, nil, err)
		return
	}

	// jsonData, err := ProtoSliceToJSON(protoItems)
	jsonData, err := json.Marshal(data)
	if err != nil {
		response.JSON(c, nil, err)
		return
	}
	var jsonObject map[string]interface{}
	err = json.Unmarshal(jsonData, &jsonObject)

	response.JSON(c, jsonObject, err)
}

// 投放计划编辑
func (Advertising) PublishScheduleSave(c *gin.Context) {
	var params advertisingc.PublishScheduleSaveReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishSchedule{}.PublishScheduleSave(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放计划审核
func (Advertising) PublishScheduleAudit(c *gin.Context) {
	var params advertisingc.PublishScheduleAuditReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	params.MerchantId = c.GetString("merchant_id")
	params.MerchantName = c.GetString("merchant_name")
	params.CreateUser = c.GetString("user_id")
	params.CreateUsername = c.GetString("username")
	err := advertising.PublishSchedule{}.PublishScheduleAudit(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放计划审核列表
func (Advertising) PublishScheduleAuditLogList(c *gin.Context) {
	var params advertisingc.PublishScheduleAuditLogListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishSchedule{}.PublishScheduleAuditLogList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 投放计划审核列表
func (Advertising) PublishScheduleAuditLogListOrderInfo(c *gin.Context) {
	var params advertisingc.SPublishScheduleAuditLogListOrderInfoReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishSchedule{}.PublishScheduleAuditLogListOrderInfo(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 商户列表
func (Advertising) PublishMerchantList(c *gin.Context) {
	var params advertisingc.PublishMerchantListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishDevice{}.PublishMerchantList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 商户配置投放设备组
func (Advertising) PublishMerchantManage(c *gin.Context) {
	var params advertisingc.PublishMerchantManageReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishDevice{}.PublishMerchantManage(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放设备组设备列表
func (Advertising) PublishDeviceList(c *gin.Context) {
	var params advertisingc.PublishDeviceListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishDevice{}.PublishDeviceList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 投放设备组列表
func (Advertising) PublishDeviceGroupList(c *gin.Context) {
	var params advertisingc.PublishDeviceGroupListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, count, err := advertising.PublishDevice{}.PublishDeviceGroupList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  data,
	}, err)
}

// 投放设备组新增编辑
func (Advertising) PublishDeviceGroupSave(c *gin.Context) {
	var params advertisingc.PublishDeviceGroupSaveReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishDevice{}.PublishDeviceGroupSave(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放设备组删除
func (Advertising) PublishDeviceGroupDelete(c *gin.Context) {
	var params advertisingc.PublishDeviceGroupDeleteReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishDevice{}.PublishDeviceGroupDelete(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 投放设备组配置设备
func (Advertising) PublishDeviceGroupManage(c *gin.Context) {
	var params advertisingc.PublishDeviceGroupManageReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.PublishDevice{}.PublishDeviceGroupManage(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 广告管理 -- 节目清单
func (Advertising) AdvertisingList(c *gin.Context) {
	var params struct {
		RobotName    string `json:"robot_name"`
		TerminalType string `json:"terminal_type"`
		Page         int32  `json:"page"`
		Limit        int32  `json:"limit"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, count, err := advertising.Advertising{}.AdvertisingList(c.Request.Context(), params.RobotName, params.TerminalType, params.Page, params.Limit)
	response.JSON(c, gin.H{
		"count": count,
		"list":  list,
	}, err)
}

// 广告管理 -- 节目清单排序
func (Advertising) AdvertisingSort(c *gin.Context) {
	var params struct {
		RobotName    string `json:"robot_name"`
		TerminalType string `json:"terminal_type"`
		Page         int32  `json:"page"`
		Limit        int32  `json:"limit"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, count, err := advertising.Advertising{}.AdvertisingList(c.Request.Context(), params.RobotName, params.TerminalType, params.Page, params.Limit)
	response.JSON(c, gin.H{
		"count": count,
		"list":  list,
	}, err)
}

// 广告管理 -- 节目播放清单
func (Advertising) AdvertisingPlayList(c *gin.Context) {
	var params struct {
		RobotName    string `json:"robot_name"`
		TerminalType string `json:"terminal_type"`
		Page         int32  `json:"page"`
		Limit        int32  `json:"limit"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, count, err := advertising.Advertising{}.AdvertisingPlayList(c.Request.Context(), params.RobotName, params.TerminalType, params.Page, params.Limit)
	response.JSON(c, gin.H{
		"count": count,
		"list":  list,
	}, err)
}

// 支持活动 -- 创建支持活动
func (Advertising) SupportActivityCreate(c *gin.Context) {
	var params advertisingc.SupportActivityCreateReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	id, err := advertising.SupportActivity{}.SupportActivityCreate(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"id": id,
	}, err)
}

// 支持活动 -- 更新支持活动
func (Advertising) SupportActivityUpdate(c *gin.Context) {
	var params advertisingc.SupportActivityUpdateReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.SupportActivity{}.SupportActivityUpdate(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 支持活动 -- 删除支持活动
func (Advertising) SupportActivityDelete(c *gin.Context) {
	var params advertisingc.SupportActivityDeleteReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.SupportActivity{}.SupportActivityDelete(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 支持活动 -- 获取活动详情
func (Advertising) SupportActivityDetail(c *gin.Context) {
	var params advertisingc.SupportActivityDetailReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, err := advertising.SupportActivity{}.SupportActivityDetail(c.Request.Context(), &params)
	response.JSON(c, data, err)
}

// 支持活动 -- 获取支持活动列表
func (Advertising) SupportActivityList(c *gin.Context) {
	var params advertisingc.SupportActivityListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, count, err := advertising.SupportActivity{}.SupportActivityList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
		"list":  list,
	}, err)
}

// 支持活动 -- 修改活动状态
func (Advertising) SupportActivityChangeStatus(c *gin.Context) {
	var params advertisingc.SupportActivityChangeStatusReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.SupportActivity{}.SupportActivityChangeStatus(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// 支持活动 -- 检查同名活动是否存在
func (Advertising) SupportActivitySameNameExist(c *gin.Context) {
	var params advertisingc.SupportActivitySameNameExistReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	count, err := advertising.SupportActivity{}.SupportActivitySameNameExist(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"count": count,
	}, err)
}

// 支持活动 -- 根据素材ID获取关联的活动列表
func (Advertising) SupportActivityGetActivityListByMaterialIDs(c *gin.Context) {
	var params advertisingc.SupportActivityGetActivityListByMaterialIDsReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, err := advertising.SupportActivity{}.SupportActivityGetActivityListByMaterialIDs(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"list": list,
	}, err)
}

// 支持活动 -- 获取活动关联的素材ID列表
func (Advertising) SupportActivityGetMaterialIDsList(c *gin.Context) {
	var params advertisingc.SupportActivityGetMaterialIDsListReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	list, err := advertising.SupportActivity{}.SupportActivityGetMaterialIDsList(c.Request.Context(), &params)
	response.JSON(c, gin.H{
		"list": list,
	}, err)
}

// 支持活动 -- 更新活动素材ID
func (Advertising) SupportActivitySetMaterialIDs(c *gin.Context) {
	var params advertisingc.SupportActivitySetMaterialIDsReq
	c.ShouldBindBodyWith(&params, binding.JSON)

	err := advertising.SupportActivity{}.SupportActivitySetMaterialIDs(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}